package com.mmall.admin.shiro;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mmall.admin.mapper.AdminMapper;
import com.mmall.admin.pojo.entity.AdminEntity;
import com.mmall.common.base.ServerResponse;
import com.mmall.common.util.SpringUtil;
import jodd.util.StringPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author gg
 * @version ShiroBaseFilter.java, v 0.1 2019-05-13 16:26 gg
 */
@Slf4j
class ShiroBaseFilter {

    private static final String SHOP_ID = "ShopId";

    /**
     * 跨域解决方案，基于shiroFilter 的 preHandle进行解决
     * shiro 在处理请求时，会使用类似于aop 的 前置方法
     * 在此处判断 如果是option 请求则直接放过
     *
     * @param request  ServletRequest
     * @param response ServletResponse
     * @return boolean
     */
    boolean preHandle(ServletRequest request, ServletResponse response) {
        HttpServletRequest httpRequest = WebUtils.toHttp(request);
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpResponse.setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"));
            httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
            httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
            //防止乱码，适用于传输JSON数据
            httpResponse.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpResponse.setStatus(HttpStatus.OK.value());
            return true;
        }
        return false;
    }

    static ShiroUser getShiroUser(ServletRequest request) {
        String id = WebUtils.toHttp(request).getHeader("Authorization");
        SessionDaoConfig sessionDaoConfig = new SessionDaoConfig();
        Session session = sessionDaoConfig.doReadSession(id);
        if (session == null) {
            return null;
        }
        MmallSimpleSession customSession = (MmallSimpleSession) session;
        ShiroUser shiroUser = customSession.getShiroUser();
        if (shiroUser == null) {
            return null;
        }
        return shiroUser;
    }

    /**
     * 此处引申一个企业中可能遇到的权限校验
     * 假如平台有多个商户 持有不同的shopId，一个商户管理员在浏览自己的后台时，必须传shopId过来
     * 在此处校验是否有shopId对应的商户页面的访问权限
     *
     * @param request   ServletRequest
     * @param shiroUser ShiroUser
     * @return Boolean
     */
    static Boolean checkShopId(ServletRequest request, ShiroUser shiroUser, ServletResponse response) {
        AdminMapper adminMapper = SpringUtil.getBean(AdminMapper.class);
        AdminEntity adminEntity = adminMapper.selectByLoginName(shiroUser.getUsername());
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rsp = (HttpServletResponse) response;
        String shopIds = adminEntity.getShopIds();
        String shopIdHeader = req.getHeader(SHOP_ID);
        if (StringUtils.isBlank(shopIdHeader)) {
            shopIdHeader = request.getParameter("shopId");
            if (StringUtils.isBlank(shopIdHeader)) {
                log.error("shopId 为空! 用户名:{}", shiroUser.getUsername());
                ServerResponse error = ServerResponse.createByErrorCodeMessage(1, "shopId 为空!");
                String errorStr = JSON.toJSONString(error);
                rsp.setHeader("Error", errorStr);
                return false;
            }
        }
        String shopId = shopIdHeader.trim();
        if (StringUtils.isBlank(shopId)) {
            log.error("shopId 为空!! 用户名:{}", shiroUser.getUsername());
            ServerResponse error = ServerResponse.createByErrorCodeMessage(1, "shopId 为空!!");
            String errorStr = JSON.toJSONString(error);
            rsp.setHeader("Error", errorStr);
            return false;
        }
        if (StringUtils.isBlank(shopIds)) {
            log.error("用户拥有的客户权限 为空! 用户名:{}", shiroUser.getUsername());
            ServerResponse error = ServerResponse.createByErrorCodeMessage(1, "用户拥有的客户权限 为空!");
            String errorStr = JSON.toJSONString(error);
            rsp.setHeader("Error", errorStr);
            return false;
        }
        List<String> shopIdList = Lists.newArrayList(shopIds.split(StringPool.COMMA));
        List<Integer> shopIdIntList = Lists.newArrayList();
        shopIdList.forEach(shopIdStr -> {
            shopIdIntList.add(Integer.valueOf(shopIdStr.trim()));
        });
        if (CollectionUtils.isEmpty(shopIdList)) {
            log.error("用户拥有的客户权限 为空!! 用户名:{}", shiroUser.getUsername());
            ServerResponse error = ServerResponse.createByErrorCodeMessage(1, "用户拥有的客户权限 为空!!");
            String errorStr = JSON.toJSONString(error);
            rsp.setHeader("Error", errorStr);
            return false;
        }
        if (!shopIdIntList.contains(Integer.valueOf(shopId))) {
            log.error("用户没有该客户权限 ! 用户名:{},客户id:{}", shiroUser.getUsername(), shopId);
            ServerResponse error = ServerResponse.createByErrorCodeMessage(1, "用户没有该客户权限 !");
            String errorStr = JSON.toJSONString(error);
            rsp.setHeader("Error", errorStr);
            return false;
        }
        return true;
    }

}